package fda.base;

import java.util.LinkedList;
import java.util.List;

public class IOCounter {
	
	private static IOCounter instance = null;
	
	private int blockCounter = 0;
	private long startTime;
	private int tupleCounter = 0;
	
	private final List<Long> memUsed =new LinkedList<>();
	private long maxTotal = 0;
	private long maxUsed = 0;
	
	private IOCounter() {
		startTime = System.currentTimeMillis();
	};
	
	public static IOCounter getInst(){
		if(instance == null)
			instance = new IOCounter();
		return instance;
	}
	
	/**
	 * increment counter for 1 block IO
	 */
	public void incr_block(){
		blockCounter++;
		updateMemory();
	}
	
	/**
	 * increment one tuple (when 40 tuples) one IO is incremented
	 */
	public void incr_tuple(){
		tupleCounter++;
		
		if(tupleCounter > Constants.MAX_TYPLES_IN_BLOCK - 1){
			blockCounter++;
			tupleCounter = 0;
		}
	}
	
	public int getIO(){
		return blockCounter;
	}

	public void printReport() {
		System.out.print("\nTotal time:\t" + (System.currentTimeMillis() - startTime) + " ms");
		System.out.print("\nBlocks IO:\t" + blockCounter + " (blocks)");
		System.out.print(String.format("\nMemory: total_available=%d(Kb)\tmaximum_used=%d(Kb)", maxTotal/1024, maxUsed/1024));
		System.out.print(getDiagram());
	}

	public void updateMemory(){
		long free = Runtime.getRuntime().freeMemory();
		long total = Runtime.getRuntime().totalMemory();
		long used = total - free;
		
		if(total > maxTotal)
			maxTotal = total;
		
		if(used > maxUsed)
			maxUsed = used;
		
		memUsed.add(used);
		
	}
	
	private String getDiagram() {
		int LINES = 30;
		int MAX_LINE_LENGTH = 60;
		StringBuilder sb = new StringBuilder();
		int step = (int) Math.floor(memUsed.size()/LINES);
		
		
		sb.append("\n\n");
		appendHeader(MAX_LINE_LENGTH - 8, sb);
		for(int i = 0; i < memUsed.size(); i += step){
			int prcent = (int) (memUsed.get(i)*100/maxTotal);
			appendLine(sb, prcent, MAX_LINE_LENGTH);
		}
		appendHeader(MAX_LINE_LENGTH - 8, sb);
		return sb.toString();
	}

	private void appendLine(StringBuilder sb, int prcent, int max) {
		int numberOfStars = max * prcent/100;
		sb.append("\n");
		for(int i = 0; i < max; ++i){
			if(i < numberOfStars)
				sb.append("*");
			else
				sb.append(".");
		}
	}
	
	private void appendHeader(int maxLength, StringBuilder sb) {
		sb.append("\n0%");
		for(int i = 0; i < maxLength; ++i){
			if(i == maxLength/2)
				sb.append("50%");
			else
				sb.append("-");
		}
		sb.append("100%");
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
